
package vec

import (
	"rand"
	"math"
)

func (a Vector) Add(b Vector) Vector {

	an := len(a.V)
	bn := len(b.V)
	n := max(an, bn)

	for i := 0; i < n; i++ {
		a.V[i%an] += b.V[i%bn]
	}

	return a
}

func (a Vector) AddWeight(b Vector, s float) Vector {

	an := len(a.V)
	bn := len(b.V)
	n := max(an, bn)

	for i := 0; i < n; i++ {
		a.V[i%an] += b.V[i%bn] * s
	}

	return a
}

func (a Vector) Sub(b Vector) Vector {

	an := len(a.V)
	bn := len(b.V)
	n := max(an, bn)

	for i := 0; i < n; i++ {
		a.V[i%an] -= b.V[i%bn]
	}

	return a
}

func (a Vector) Randomize() Vector {

	for i := 0; i < len(a.V); i++ {
		a.V[i] = rand.Float()
	}

	return a
}

func (a Vector) Magnitude() float {

	sum := float(0)

	for i := 0; i < len(a.V); i++ {
		sum += a.V[i] * a.V[i]
	}

	return float(math.Sqrt(float64(sum)))
}

func (a Vector) Mean () float {

	sum := float(0)

	for i := 0; i < len(a.V); i++ {
		sum += a.V[i]
	}

	return sum / float (a.Length ())
}

func (a Vector) Normalize() Vector {

	mag := a.Magnitude()

	for i := 0; i < len(a.V); i++ {
		a.V[i] /= mag
	}

	return a
}

func (a Vector) Limit (lower, upper float) {

	for i := 0; i < len (a.V); i++ {
		if a.V[i] < lower { a.V[i] = lower }
		if a.V[i] > upper { a.V[i] = upper }
	}
}

func Random(n int) Vector { return Zeros(n).Randomize() }

func (a Vector) Scale(f float) Vector {

	for i := 0; i < len(a.V); i++ {
		a.V[i] *= f
	}

	return a
}

func Sum(args []Vector) Vector {

	n := len(args[0].V)

	res := Zeros(n)

	for _, a := range args {

		res.Add(a)
	}

	return res
}

func Dot(a, b Vector) float {

	an := len(a.V)
	bn := len(b.V)
	n := max(an, bn)
	res := float(0.0)

	for i := 0; i < n; i++ {
		res += a.V[i%an] * b.V[i%bn]
	}

	return res
}

